home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_2 / vsrc.tar / voyager7_src / commands.c < prev    next >
C/C++ Source or Header  |  1991-02-27  |  31KB  |  1,461 lines

  1. /*
  2. // Abstract:
  3. //    COMMANDS---Parse Command Line
  4. //
  5. //    The Parse Command Line module parses a Voyager command and
  6. //    dispatches to the appropriate routine.
  7. //
  8. // Author:
  9. //    Derek S. Nickel
  10. //
  11. // Creation date:
  12. //    27 October 1990
  13. //
  14. // History:
  15. // V01-001    Derek S. Nickel        27-OCT-1990
  16. //    Original.
  17. //
  18. */
  19.  
  20. #include <malloc.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24.  
  25. #include "commands.h"
  26. #include "dump.h"
  27. #include "find.h"
  28. #include "list.h"
  29. #include "memory.h"
  30. #include "modes.h"
  31. #include "objects.h"
  32. #include "pager.h"
  33. #include "ports.h"
  34. #include "search.h"
  35. #include "version.h"
  36.  
  37. extern void output_help(void);
  38. extern void unany(char *q);
  39.  
  40. /***********************************************************************
  41.     Keyword Data Structures
  42. ***********************************************************************/
  43.  
  44. typedef struct _keyword_t keyword_t;
  45. typedef void (*cmd_proc_t)(void);
  46.  
  47. struct _keyword_t {
  48.     char *keyword;
  49.     cmd_proc_t procedure;
  50. };
  51.  
  52. /***********************************************************************
  53.     Local Routines
  54. ***********************************************************************/
  55.  
  56. static void ask(char *prompt, char *cmdline);
  57. static int check_maxparm(void);
  58. static void cmd_comment_address(void);
  59. static void cmd_comment_code(void);
  60. static void cmd_comment_list(void);
  61. static void cmd_dump(void);
  62. static void cmd_dump_alt(void);
  63. static void cmd_dump_hex(void);
  64. static void cmd_dump_text(void);
  65. static void cmd_examine(void);
  66. static void cmd_examine_hash_table(void);
  67. static void cmd_examine_link_table(void);
  68. static void cmd_exit(void);
  69. static void cmd_examine_message_table(void);
  70. static void cmd_examine_short_library(void);
  71. static void cmd_find(void);
  72. static void cmd_header(void);
  73. static void cmd_help(void);
  74. static void cmd_list(void);
  75. static void cmd_load(void);
  76. static void cmd_merge(void);
  77. static void cmd_search(void);
  78. static void cmd_set(void);
  79. static void cmd_set_limit(void);
  80. static void cmd_set_mode(void);
  81. static void cmd_show(void);
  82. static void cmd_show_limit(void);
  83. static void cmd_show_memory(void);
  84. static void cmd_show_modes(void);
  85. static void cmd_show_ports(void);
  86. static void cmd_show_version(void);
  87. static void cmd_sort(void);
  88. static void cmd_unassemble(void);
  89. static void cmd_uncomment_address(void);
  90. static void cmd_uncomment_code(void);
  91. static void cmd_uncontinue(void);
  92. static void cmd_unload(void);
  93. static void cmd_unthread(void);
  94.  
  95. static int convert_address(char *token, bin5_t *adr);
  96. static int get_address(bin5_t *adr);
  97. static int get_address_opt(bin5_t *adr);
  98. static int get_address_range(bin5_t *start, bin5_t *end);
  99. static int get_dec_number(char *prompt, bin5_t *number);
  100. static char *get_first_token(void);
  101. static int get_hex_number(char *prompt, bin5_t *number);
  102. static char *get_next_token(char *prompt);
  103. static char *get_next_token_opt(void);
  104. static char *get_rest_of_line(char *prompt);
  105. static char *get_rest_of_line_opt(void);
  106. static void lookup_command(char *input, const keyword_t *kw,
  107.     cmd_proc_t *proc,int *matches );
  108. static void lookup_command_exact(char *input, const keyword_t *kw,
  109.     cmd_proc_t *proc,int *matches );
  110.  
  111. /***********************************************************************
  112.     Command Tables.
  113. ***********************************************************************/
  114.  
  115. static const keyword_t verbs[] = {
  116.     "DUMP",        cmd_dump,
  117.     "EXAMINE",    cmd_examine,
  118.     "EXIT",        cmd_exit,
  119.     "FIND",        cmd_find,
  120.     "HEADER",    cmd_header,
  121.     "HELP",        cmd_help,
  122.     "LIST",        cmd_list,
  123.     "LOAD",        cmd_load,
  124.     "MERGE",    cmd_merge,
  125.     "SEARCH",    cmd_search,
  126.     "SET",        cmd_set,
  127.     "SHOW",        cmd_show,
  128.     "SORT",        cmd_sort,
  129.     "UNASSEMBLE",    cmd_unassemble,
  130.     "UNCONTINUE",    cmd_uncontinue,
  131.     "UNTHREAD",    cmd_unthread,
  132.     "UNLOAD",    cmd_unload,
  133.     NULL,        NULL
  134. };
  135.  
  136. static const keyword_t verbs2[] = {
  137.     "CA",         cmd_comment_address,
  138.     "CAD",         cmd_uncomment_address,
  139.     "CC",         cmd_comment_code,
  140.     "CCD",         cmd_uncomment_code,
  141.     "CL",         cmd_comment_list,
  142.     "DA",         cmd_dump_alt,
  143.     "DH",         cmd_dump_hex,
  144.     "DT",         cmd_dump_text,
  145.     "U",         cmd_uncontinue,
  146.     "UA",         cmd_unassemble,
  147.     "UT",         cmd_unthread,
  148.     NULL,        NULL
  149. };
  150.  
  151. static const keyword_t examine_kw[] = {
  152.     "HASH_TABLE",    cmd_examine_hash_table,
  153.     "LINK_TABLE",    cmd_examine_link_table,
  154.     "MESSAGE_TABLE", cmd_examine_message_table,
  155.     "SHORT_LIBRARY", cmd_examine_short_library,
  156.     NULL,        NULL
  157. };
  158.  
  159. static const keyword_t set_kw[] = {
  160.     "LIMIT",    cmd_set_limit,
  161.     "MODE",        cmd_set_mode,
  162.     NULL,        NULL
  163. };
  164.  
  165. static const keyword_t show_kw[] = {
  166.     "LIMIT",    cmd_show_limit,
  167. /*    "MEMORY",    cmd_show_memory,    */
  168.     "MODES",    cmd_show_modes,
  169.     "PORTS",    cmd_show_ports,
  170.     "VERSION",    cmd_show_version,
  171.     NULL,        NULL
  172. };
  173.  
  174. /***********************************************************************
  175.     Local Data.
  176. ***********************************************************************/
  177.  
  178. static char zero = '\0';
  179. static char g_cmdline[128];
  180.  
  181. static int done = 0;
  182.  
  183. static bin5_t last_address = 0;
  184.  
  185. /***********************************************************************
  186.     Messages.
  187. ***********************************************************************/
  188.  
  189. // 00038008
  190. #define cli$_abverb \
  191. "%%CLI-W-ABKEYW, ambiguous command verb - supply more characters\n"
  192.  
  193. // 00038010
  194. #define cli$_abkeyw \
  195. "%%CLI-W-ABKEYW, ambiguous qualifier or keyword - supply more characters\n"
  196.  
  197. // 00038040
  198. #define cli$_insfprm \
  199. "%%CLI-W-INSFPRM, missing command parameters - supply all required parameters\n"
  200.  
  201. // 00038050
  202. #define cli$_ivchar \
  203. "%%CLI-W-IVCHAR, invalid numeric value - check for invalid digits\n"
  204.  
  205. // 00038060
  206. #define cli$_ivkeyw \
  207. "%%CLI-W-IVKEYW, unrecognized keyword - check validity and spelling\n"
  208.  
  209. // 00038090
  210. #define cli$_ivverb \
  211. "%%CLI-W-IVVERB, unrecognized command verb - check validity and spelling\n"
  212.  
  213. // 00038098
  214. #define cli$_maxparm \
  215. "%%CLI-W-MAXPARM, too many parameters - reenter command with fewer parameters\n"
  216.  
  217. // 00038248
  218. #define cli$_cmdseg \
  219. " \\%s\\\n"
  220.  
  221. // no numeric value...
  222. #define vgr__author \
  223. "-VOYAGER-I-AUTHOR, programmed by Derek S. Nickel\n"
  224.  
  225. // no numeric value...
  226. #define vgr__version \
  227. "%%VOYAGER-I-VERSION, this is VOYAGER version %s\n"
  228.  
  229. /***********************************************************************
  230.     parse_command
  231. ***********************************************************************/
  232.  
  233. int parse_command(void)
  234. {
  235.     int matches;
  236.     int plen;
  237.     char *p;
  238.     cmd_proc_t cmd;
  239.  
  240.     /*
  241.     // Get a command.
  242.     */
  243.  
  244.     ask("Voyager> ", g_cmdline);
  245.  
  246.     /*
  247.     // Reset the pager.
  248.     */
  249.  
  250.     pager(-1);
  251.  
  252.     /*
  253.     // Get the command verb.
  254.     */
  255.  
  256.     p = get_first_token();
  257.     plen = strlen(p);
  258.  
  259.     /*
  260.     // Dispatch to command.
  261.     */
  262.  
  263.     if (p == NULL) {
  264.         /* No Command */
  265.  
  266.     } else {
  267.         /*
  268.         // Look up in the brief/exact verbs commands table.
  269.         */
  270.  
  271.         lookup_command_exact(p, verbs2, &cmd, &matches);
  272.  
  273.         /*
  274.         // If not found, look up in the verbs command table.
  275.         */
  276.  
  277.         if (matches == 0)
  278.             lookup_command(p, verbs, &cmd, &matches);
  279.  
  280.         /*
  281.         // Process based on number of matches.
  282.         */
  283.  
  284.         if (matches < 1) {
  285.             /* Unrecognized command verb */
  286.             pager(0);
  287.             printf(cli$_ivverb);
  288.             pager(0);
  289.             printf(cli$_cmdseg,p);
  290.  
  291.         } else if (matches > 1) {
  292.             /* Ambiguous qualifier or keyword */
  293.             pager(0);
  294.             printf(cli$_abverb);
  295.             pager(0);
  296.             printf(cli$_cmdseg,p);
  297.  
  298.         } else {
  299.             /* Execute the command */
  300.             cmd();
  301.         }
  302.     }
  303.  
  304.     return done;
  305. }
  306.  
  307. /***********************************************************************
  308.     cmd_comment_address
  309. ***********************************************************************/
  310.  
  311. static void cmd_comment_address(void)
  312. {
  313.     char *rest;
  314.     int port_no;
  315.     bin5_t port_adr;
  316.     bin5_t adr;
  317.  
  318.     /*
  319.     // Get address and comment; add to database.
  320.     */
  321.  
  322.     if (get_address(&adr))
  323.       if (rest = get_rest_of_line("_Comment: "))
  324.         if (xlate_adr(adr, &port_no, &port_adr))
  325.           AddTextLine(ports[port_no].ca_file, port_adr, rest);
  326. }
  327.  
  328. /***********************************************************************
  329.     cmd_comment_code
  330. ***********************************************************************/
  331.  
  332. static void cmd_comment_code(void)
  333. {
  334.     char *rest;
  335.     int port_no;
  336.     bin5_t port_adr;
  337.     bin5_t adr;
  338.  
  339.     /*
  340.     // Get address and comment; add to database.
  341.     */
  342.  
  343.     if (get_address(&adr))
  344.       if (rest = get_rest_of_line("_Comment: "))
  345.         if (xlate_adr(adr, &port_no, &port_adr))
  346.           AddTextLine(ports[port_no].cc_file, port_adr, rest);
  347. }
  348.  
  349. /***********************************************************************
  350.     cmd_comment_list
  351. ***********************************************************************/
  352.  
  353. static void cmd_comment_list(void)
  354. {
  355.     char *rem;
  356.     bin5_t adr;
  357.  
  358.     if (get_address(&adr)) if (check_maxparm()) {
  359.         rem = get_address_comment(adr);
  360.         if (*rem) {
  361.             pager(0);
  362.             printf("(addr) %05lX: %s\n", adr, rem);
  363.         }
  364.  
  365.         rem = get_code_comment(adr);
  366.         if (*rem) {
  367.             pager(0);
  368.             printf("(code) %05lX: %s\n", adr, rem);
  369.         }
  370.     }
  371. }
  372.  
  373. /***********************************************************************
  374.     cmd_dump
  375. ***********************************************************************/
  376.  
  377. static void cmd_dump(void)
  378. {
  379.     bin5_t adr;
  380.  
  381.     if (get_address_opt(&adr))
  382.       if (check_maxparm())
  383.         dump_memory(adr,0);
  384. }
  385.  
  386. /***********************************************************************
  387.     cmd_dump_alt
  388. ***********************************************************************/
  389.  
  390. static void cmd_dump_alt(void)
  391. {
  392.     bin5_t adr;
  393.  
  394.     if (get_address_opt(&adr))
  395.       if (check_maxparm()) 
  396.         dump_memory(adr,3);
  397. }
  398.  
  399. /***********************************************************************
  400.     cmd_dump_hex
  401. ***********************************************************************/
  402.  
  403. static void cmd_dump_hex(void)
  404. {
  405.     bin5_t adr;
  406.  
  407.     if (get_address_opt(&adr))
  408.       if (check_maxparm()) 
  409.         dump_memory(adr,1);
  410. }
  411.  
  412. /***********************************************************************
  413.     cmd_dump_text
  414. ***********************************************************************/
  415.  
  416. static void cmd_dump_text(void)
  417. {
  418.     bin5_t adr;
  419.  
  420.     if (get_address_opt(&adr))
  421.       if (check_maxparm()) 
  422.         dump_memory(adr,2);
  423. }
  424.  
  425. /***********************************************************************
  426.     cmd_examine
  427. ***********************************************************************/
  428.  
  429. static void cmd_examine(void)
  430. {
  431.     int matches;
  432.     char *p;
  433.     cmd_proc_t cmd;
  434.  
  435.     /*
  436.     // Get EXAMINE keyword.
  437.     */
  438.  
  439.     if (p = get_next_token("_Examine what: ")) {
  440.         /*
  441.         // Lookup the EXAMINE keyword.
  442.         */
  443.  
  444.         strupr(p);
  445.         lookup_command(p, examine_kw, &cmd, &matches);
  446.     
  447.         /*
  448.         // Process based on number of matches.
  449.         */
  450.  
  451.         if (matches < 1) {
  452.             /* Unrecognized keyword */
  453.             pager(0);
  454.             printf(cli$_ivkeyw);
  455.             pager(0);
  456.             printf(cli$_cmdseg,p);
  457.  
  458.         } else if (matches > 1) {
  459.             /* Ambiguous qualifier or keyword */
  460.             pager(0);
  461.             printf(cli$_abkeyw);
  462.             pager(0);
  463.             printf(cli$_cmdseg,p);
  464.  
  465.         } else {
  466.             /* Execute the command */
  467.             cmd();
  468.         }
  469.     }
  470. }
  471.  
  472. /***********************************************************************
  473.     cmd_examine_hash_table
  474. ***********************************************************************/
  475.  
  476. static void cmd_examine_hash_table(void)
  477. {
  478.     bin5_t adr;
  479.     bin5_t lib;
  480.  
  481.     if (get_address(&adr))
  482.       if (get_hex_number("_Library number: ", &lib))
  483.         if (check_maxparm())
  484.           display_hash_table(adr,lib);
  485. }
  486.  
  487. /***********************************************************************
  488.     cmd_examine_link_table
  489. ***********************************************************************/
  490.  
  491. static void cmd_examine_link_table(void)
  492. {
  493.     bin5_t adr;
  494.     bin5_t lib;
  495.  
  496.     if (get_address(&adr))
  497.       if (get_hex_number("_Library number: ", &lib))
  498.         if (check_maxparm())
  499.           display_link_table(adr,lib);
  500. }
  501.  
  502. /***********************************************************************
  503.     cmd_examine_message_table
  504. ***********************************************************************/
  505.  
  506. static void cmd_examine_message_table(void)
  507. {
  508.     bin5_t adr;
  509.     bin5_t lib;
  510.  
  511.     if (get_address(&adr))
  512.       if (get_hex_number("_Library number: ", &lib))
  513.         if (check_maxparm())
  514.           display_message_table(adr,lib);
  515. }
  516.  
  517. /***********************************************************************
  518.     cmd_examine_short_library
  519. ***********************************************************************/
  520.  
  521. static void cmd_examine_short_library(void)
  522. {
  523.     bin5_t adr;
  524.  
  525.     if (get_address(&adr))
  526.       if (check_maxparm())
  527.         display_short_library(adr);
  528. }
  529.  
  530. /***********************************************************************
  531.     cmd_exit
  532. ***********************************************************************/
  533.  
  534. static void cmd_exit(void)
  535. {
  536.     if (check_maxparm())
  537.       done = 1;
  538. }
  539.  
  540. /***********************************************************************
  541.     cmd_find
  542. ***********************************************************************/
  543.  
  544. static void cmd_find(void)
  545. {
  546.     bin5_t start;
  547.     bin5_t end;
  548.     char *data;
  549.  
  550.     if (get_address_range(&start,&end))
  551.       if (data = get_rest_of_line("_Search for: "))
  552.         find_comment(start,end,data);
  553. }
  554.  
  555. /***********************************************************************
  556.     cmd_header
  557. ***********************************************************************/
  558.  
  559. static void cmd_header(void)
  560. {
  561.     bin5_t adr;
  562.  
  563.     if (get_address_opt(&adr))
  564.       if (check_maxparm()) {
  565.         char buf2[4];
  566.         bin5_t flag;
  567.         bin5_t lib_no;
  568.         bin5_t obj_no;
  569.  
  570.         SetWorkPtr(adr);
  571.  
  572.         GetNNibbles(buf2,1);
  573.         flag = str2adr(buf2,0);
  574.  
  575.         GetNNibbles(buf2,3);
  576.         strrev(buf2);
  577.         lib_no = str2adr(buf2,0);
  578.  
  579.         GetNNibbles(buf2,3);
  580.         strrev(buf2);
  581.         obj_no = str2adr(buf2,0);
  582.  
  583.         pager(0);
  584.         printf("%05lX: [...] ! header: XLIB %ld %ld (%lX)\n",
  585.             adr, lib_no, obj_no, flag );
  586.       }
  587. }
  588.  
  589. /***********************************************************************
  590.     cmd_help
  591. ***********************************************************************/
  592.  
  593. static void cmd_help(void)
  594. {
  595.     if (check_maxparm())
  596.       output_help();
  597. }
  598.  
  599. /***********************************************************************
  600.     cmd_list
  601. ***********************************************************************/
  602.  
  603. static void cmd_list(void)
  604. {
  605.     bin5_t start;
  606.     bin5_t end;
  607.  
  608.     if (get_address_range(&start,&end))
  609.       if (check_maxparm())
  610.         list_comment(start,end);
  611. }
  612.  
  613. /***********************************************************************
  614.     cmd_load
  615. ***********************************************************************/
  616.  
  617. static void cmd_load(void)
  618. {
  619.     bin5_t p;
  620.     char *q;
  621.  
  622.     if (get_dec_number("_Port number: ", &p))
  623.       if (q = get_next_token("_Module: "))
  624.         if (check_maxparm())
  625.           open_port(p,q);
  626. }
  627.  
  628. /***********************************************************************
  629.     cmd_merge
  630. ***********************************************************************/
  631.  
  632. static void cmd_merge(void)
  633. {
  634.     bin5_t p;
  635.     char *q;
  636.  
  637.     if (get_dec_number("_Port number: ", &p))
  638.       if (q = get_next_token("_New module: "))
  639.         if (check_maxparm())
  640.           merge_port(p,q);
  641. }
  642.  
  643. /***********************************************************************
  644.     cmd_search
  645. ***********************************************************************/
  646.  
  647. static void cmd_search(void)
  648. {
  649.     bin5_t start;
  650.     bin5_t end;
  651.     char *data;
  652.  
  653.     if (get_address_range(&start,&end))
  654.       if (data = get_next_token("_Search for: "))
  655.         if (check_maxparm())
  656.           search_memory(start,end,data);
  657. }
  658.  
  659. /***********************************************************************
  660.     cmd_set
  661. ***********************************************************************/
  662.  
  663. static void cmd_set(void)
  664. {
  665.     int matches;
  666.     char *p;
  667.     cmd_proc_t cmd;
  668.  
  669.     /*
  670.     // Get SET keyword.
  671.     */
  672.  
  673.     if (p = get_next_token("_Set what: ")) {
  674.         /*
  675.         // Lookup the SET keyword.
  676.         */
  677.  
  678.         strupr(p);
  679.         lookup_command(p, set_kw, &cmd, &matches);
  680.     
  681.         /*
  682.         // Process based on number of matches.
  683.         */
  684.  
  685.         if (matches < 1) {
  686.             /* Unrecognized keyword */
  687.             pager(0);
  688.             printf(cli$_ivkeyw);
  689.             pager(0);
  690.             printf(cli$_cmdseg,p);
  691.  
  692.         } else if (matches > 1) {
  693.             /* Ambiguous qualifier or keyword */
  694.             pager(0);
  695.             printf(cli$_abkeyw);
  696.             pager(0);
  697.             printf(cli$_cmdseg,p);
  698.  
  699.         } else {
  700.             /* Execute the command */
  701.             cmd();
  702.         }
  703.     }
  704. }
  705.  
  706. /***********************************************************************
  707.     cmd_set_limit
  708. ***********************************************************************/
  709.  
  710. static void cmd_set_limit(void)
  711. {
  712.     bin5_t p;
  713.  
  714.     /*
  715.     // Get SET LIMIT size.
  716.     */
  717.  
  718.     if (get_dec_number("_Limit: ", &p))
  719.       if (check_maxparm()) {
  720.         if (p < 1) p = 1;
  721.         modes.limit = p;
  722.       }
  723. }
  724.  
  725. /***********************************************************************
  726.     cmd_set_mode
  727. ***********************************************************************/
  728.  
  729. static void cmd_set_mode(void)
  730. {
  731.     char *p;
  732.     int plen;
  733.  
  734.     /*
  735.     // Get SET MODE keyword.
  736.     */
  737.  
  738.     if (p = get_next_token("_Mode: "))
  739.       if (check_maxparm()) {
  740.         plen = strlen(p);
  741.         strupr(p);
  742.  
  743.         if (!strncmp(p,"P",plen)) {
  744.             /* Ambiguous qualifier or keyword */
  745.             pager(0);
  746.             printf(cli$_abkeyw);
  747.             pager(0);
  748.             printf(cli$_cmdseg,p);
  749.  
  750.         } else if (!strncmp(p,"NOP",plen)) {
  751.             /* Ambiguous qualifier or keyword */
  752.             pager(0);
  753.             printf(cli$_abkeyw);
  754.             pager(0);
  755.             printf(cli$_cmdseg,p);
  756.  
  757.         } else if (!strncmp(p,"FOLLOW",plen)) {
  758.             /* SET MODE FOLLOW */
  759.             modes.follow = 1;
  760.  
  761.         } else if (!strncmp(p,"NOFOLLOW",plen)) {
  762.             /* SET MODE NOFOLLOW */
  763.             modes.follow = 0;
  764.  
  765.         } else if (!strncmp(p,"INFO",plen)) {
  766.             /* SET MODE INFO */
  767.             modes.info = 1;
  768.  
  769.         } else if (!strncmp(p,"NOINFO",plen)) {
  770.             /* SET MODE NOINFO */
  771.             modes.info = 0;
  772.  
  773.         } else if (!strncmp(p,"PAGER",plen)) {
  774.             /* SET MODE PAGER */
  775.             modes.pager = 1;
  776.  
  777.         } else if (!strncmp(p,"NOPAGER",plen)) {
  778.             /* SET MODE NOPAGER */
  779.             modes.pager = 0;
  780.  
  781.         } else if (!strncmp(p,"PROMPT",plen)) {
  782.             /* SET MODE PROMPT */
  783.             modes.prompt = 1;
  784.  
  785.         } else if (!strncmp(p,"NOPROMPT",plen)) {
  786.             /* SET MODE NOPROMPT */
  787.             modes.prompt = 0;
  788.  
  789.         } else if (!strncmp(p,"STOP",plen)) {
  790.             /* SET MODE STOP */
  791.             modes.stop = 1;
  792.  
  793.         } else if (!strncmp(p,"NOSTOP",plen)) {
  794.             /* SET MODE NOSTOP */
  795.             modes.stop = 0;
  796.  
  797.         } else {
  798.             /* Unrecognized keyword */
  799.             pager(0);
  800.             printf(cli$_ivkeyw);
  801.             pager(0);
  802.             printf(cli$_cmdseg,p);
  803.         }
  804.       }
  805. }
  806.  
  807. /***********************************************************************
  808.     cmd_show
  809. ***********************************************************************/
  810.  
  811. static void cmd_show(void)
  812. {
  813.     int matches;
  814.     char *p;
  815.     cmd_proc_t cmd;
  816.  
  817.     /*
  818.     // Get SHOW keyword.
  819.     */
  820.  
  821.     if (p = get_next_token("_Show what: ")) {
  822.         /*
  823.         // Lookup the SHOW keyword.
  824.         */
  825.  
  826.         strupr(p);
  827.         lookup_command(p, show_kw, &cmd, &matches);
  828.     
  829.         /*
  830.         // Process based on number of matches.
  831.         */
  832.  
  833.         if (matches < 1) {
  834.             /* Unrecognized keyword */
  835.             pager(0);
  836.             printf(cli$_ivkeyw);
  837.             pager(0);
  838.             printf(cli$_cmdseg,p);
  839.  
  840.         } else if (matches > 1) {
  841.             /* Ambiguous qualifier or keyword */
  842.             pager(0);
  843.             printf(cli$_abkeyw);
  844.             pager(0);
  845.             printf(cli$_cmdseg,p);
  846.  
  847.         } else {
  848.             /* Execute the command */
  849.             cmd();
  850.         }
  851.     }
  852. }
  853.  
  854. /***********************************************************************
  855.     cmd_show_limit
  856. ***********************************************************************/
  857.  
  858. static void cmd_show_limit(void)
  859. {
  860.     if (!check_maxparm()) return;
  861.     pager(0);
  862.     printf("Limit = %d\n", modes.limit);
  863. }
  864.  
  865. /***********************************************************************
  866.     cmd_show_memory
  867. ***********************************************************************/
  868.  
  869. static void cmd_show_memory(void)
  870. {
  871.     if (!check_maxparm()) return;
  872.     pager(0);
  873.     printf("Memory available = %u bytes\n", _memavl());
  874. }
  875.  
  876. /***********************************************************************
  877.     cmd_show_modes
  878. ***********************************************************************/
  879.  
  880. static void cmd_show_modes(void)
  881. {
  882.     if (!check_maxparm()) return;
  883.     pager(0); printf("Current modes:\n");
  884.     pager(0); printf("  %sfollow\n", modes.follow ? "" : "no ");
  885.     pager(0); printf("  %sinfo\n", modes.info ? "" : "no ");
  886.     pager(0); printf("  %spager\n", modes.pager ? "" : "no ");
  887.     pager(0); printf("  %sprompt\n", modes.prompt ? "" : "no ");
  888.     pager(0); printf("  %sstop\n", modes.stop ? "" : "no ");
  889. }
  890.  
  891. /***********************************************************************
  892.     cmd_show_ports
  893. ***********************************************************************/
  894.  
  895. static void cmd_show_ports(void)
  896. {
  897.     int port_no;
  898.     int port_cnt = 0;
  899.     int cnt;
  900.  
  901.     if (!check_maxparm()) return;
  902.  
  903.     for (port_no = 0; port_no <= 2; port_no++) {
  904.         if (ports[port_no].loaded) {
  905.             port_cnt++;
  906.             pager(0);
  907.             printf("Port %d: %s\n", port_no,
  908.                 ports[port_no].module);
  909.  
  910.             pager(0);
  911.             printf("        address range: %05lX:%05lX\n",
  912.                 ports[port_no].min_adr,
  913.                 ports[port_no].max_adr);
  914.  
  915.             cnt = ports[port_no].ca_file->count;
  916.             pager(0);
  917.             printf("        %d address comment%s\n",
  918.                 cnt, cnt == 1 ? "" : "s");
  919.  
  920.             cnt = ports[port_no].cc_file->count;
  921.             pager(0);
  922.             printf("        %d code comment%s\n",
  923.                 cnt, cnt == 1 ? "" : "s");
  924.         }
  925.     }
  926.  
  927.     if (port_cnt == 0) {
  928.         pager(0);
  929.         printf("No ports loaded\n");
  930.     }
  931. }
  932.  
  933. /***********************************************************************
  934.     cmd_show_version
  935. ***********************************************************************/
  936.  
  937. static void cmd_show_version(void)
  938. {
  939.     if (!check_maxparm()) return;
  940.     pager(0); printf(vgr__version, VERSION);
  941.     pager(0); printf(vgr__author);
  942. }
  943.  
  944. /***********************************************************************
  945.     cmd_sort
  946. ***********************************************************************/
  947.  
  948. static void cmd_sort(void)
  949. {
  950.     bin5_t p;
  951.  
  952.     if (get_dec_number("_Port number: ", &p))
  953.       if (check_maxparm())
  954.         sort_port(p);
  955. }
  956.  
  957. /***********************************************************************
  958.     cmd_unassemble
  959. ***********************************************************************/
  960.  
  961. static void cmd_unassemble(void)
  962. {
  963.     modes.unmode = 1;
  964.     cmd_uncontinue();
  965. }
  966.  
  967. /***********************************************************************
  968.     cmd_uncomment_address
  969. ***********************************************************************/
  970.  
  971. static void cmd_uncomment_address(void)
  972. {
  973.     int port_no;
  974.     bin5_t port_adr;
  975.     bin5_t adr;
  976.  
  977.     if (get_address(&adr))
  978.       if (check_maxparm())
  979.         if (xlate_adr(adr, &port_no, &port_adr))
  980.           DelTextLine(ports[port_no].ca_file, port_adr);
  981. }
  982.  
  983. /***********************************************************************
  984.     cmd_uncomment_code
  985. ***********************************************************************/
  986.  
  987. static void cmd_uncomment_code(void)
  988. {
  989.     int port_no;
  990.     bin5_t port_adr;
  991.     bin5_t adr;
  992.  
  993.     if (get_address(&adr))
  994.       if (check_maxparm())
  995.         if (xlate_adr(adr, &port_no, &port_adr))
  996.           DelTextLine(ports[port_no].cc_file, port_adr);
  997. }
  998.  
  999. /***********************************************************************
  1000.     cmd_uncontinue
  1001. ***********************************************************************/
  1002.  
  1003. static void cmd_uncontinue(void)
  1004. {
  1005.     bin5_t adr;
  1006.  
  1007.     if (get_address_opt(&adr))
  1008.       if (check_maxparm()) {
  1009.         SetWorkPtr(adr);
  1010.         unany(&zero);
  1011.       }
  1012. }
  1013.  
  1014. /***********************************************************************
  1015.     cmd_unload
  1016. ***********************************************************************/
  1017.  
  1018. static void cmd_unload(void)
  1019. {
  1020.     bin5_t p;
  1021.  
  1022.     if (get_dec_number("_Port number: ", &p))
  1023.       if (check_maxparm())
  1024.         close_port(p);
  1025. }
  1026.  
  1027. /***********************************************************************
  1028.     cmd_unthread
  1029. ***********************************************************************/
  1030.  
  1031. static void cmd_unthread(void)
  1032. {
  1033.     modes.unmode = 0;
  1034.     cmd_uncontinue();
  1035. }
  1036.  
  1037. /***********************************************************************
  1038.     ask
  1039. ***********************************************************************/
  1040.  
  1041. static void ask(char *prompt, char *cmdline)
  1042. {
  1043.     /*
  1044.     // Prompt the user for input...
  1045.     */
  1046.  
  1047.     *cmdline = '\0';
  1048.  
  1049.     do {
  1050.         if (modes.prompt) printf(prompt);
  1051.         gets(cmdline);
  1052.     } while (*cmdline == '\0');
  1053. }
  1054.  
  1055. /***********************************************************************
  1056.     lookup_command_exact
  1057. ***********************************************************************/
  1058.  
  1059. static void lookup_command_exact(
  1060.     char *input,
  1061.     const keyword_t *kw,
  1062.     cmd_proc_t *proc,
  1063.     int *matches )
  1064. {
  1065.     *proc = NULL;
  1066.     *matches = 0;
  1067.  
  1068.     while (kw->keyword) {
  1069.         if (!strcmp(input, kw->keyword)) {
  1070.             if (*matches == 0) *proc = kw->procedure;
  1071.             (*matches)++;
  1072.         }
  1073.         kw++;
  1074.     }
  1075. }
  1076.  
  1077. /***********************************************************************
  1078.     lookup_command
  1079. ***********************************************************************/
  1080.  
  1081. static void lookup_command(
  1082.     char *input,
  1083.     const keyword_t *kw,
  1084.     cmd_proc_t *proc,
  1085.     int *matches )
  1086. {
  1087.     int ilen;
  1088.  
  1089.     *proc = NULL;
  1090.     *matches = 0;
  1091.     ilen = strlen(input);
  1092.  
  1093.     while (kw->keyword) {
  1094.         if (!strncmp(input, kw->keyword, ilen)) {
  1095.             if (*matches == 0) *proc = kw->procedure;
  1096.             (*matches)++;
  1097.         }
  1098.         kw++;
  1099.     }
  1100. }
  1101.  
  1102. /***********************************************************************
  1103.     get_first_token
  1104. ***********************************************************************/
  1105.  
  1106. static char *get_first_token(void)
  1107. {
  1108.     static char sep[] = " \t";
  1109.     char *token;
  1110.  
  1111.     /*
  1112.     // Get the first token.
  1113.     */
  1114.  
  1115.     token = strtok(g_cmdline, sep);
  1116.     strupr(token);
  1117.     return token;
  1118. }
  1119.  
  1120. /***********************************************************************
  1121.     get_next_token
  1122. ***********************************************************************/
  1123.  
  1124. static char *get_next_token(char *prompt)
  1125. {
  1126.     static char sep[] = " \t";
  1127.     char *token;
  1128.  
  1129.     /*
  1130.     // Get the next token.
  1131.     */
  1132.  
  1133.     token = strtok(NULL, sep);
  1134.  
  1135.     /*
  1136.     // If no next token, ask the user and try again.
  1137.     */
  1138.  
  1139.     if (token == NULL) {
  1140.         ask(prompt, g_cmdline);
  1141.         token = strtok(g_cmdline, sep);
  1142.     }
  1143.  
  1144.     strupr(token);
  1145.  
  1146.     /*
  1147.     // If still no next token...
  1148.     */
  1149.  
  1150.     if (token == NULL) {
  1151.         /* Missing command parameters */
  1152.         pager(0);
  1153.         printf(cli$_insfprm);
  1154.     }
  1155.  
  1156.     return token;
  1157. }
  1158.  
  1159. /***********************************************************************
  1160.     get_next_token_opt
  1161. ***********************************************************************/
  1162.  
  1163. static char *get_next_token_opt(void)
  1164. {
  1165.     static char sep[] = " \t";
  1166.     char *token;
  1167.  
  1168.     /*
  1169.     // Get the next token (optional).
  1170.     */
  1171.  
  1172.     token = strtok(NULL, sep);
  1173.     strupr(token);
  1174.     return token;
  1175. }
  1176.  
  1177. /***********************************************************************
  1178.     get_rest_of_line
  1179. ***********************************************************************/
  1180.  
  1181. static char *get_rest_of_line(char *prompt)
  1182. {
  1183.     static char sep[] = "";
  1184.     char *token;
  1185.  
  1186.     /*
  1187.     // Get the rest of the line.
  1188.     */
  1189.  
  1190.     token = strtok(NULL, sep);
  1191.  
  1192.     /*
  1193.     // If nothing available, ask the user.
  1194.     */
  1195.  
  1196.     if (token == NULL) {
  1197.         ask(prompt, g_cmdline);
  1198.         token = strtok(g_cmdline, sep);
  1199.     }
  1200.  
  1201.     /*
  1202.     // If still nothing...
  1203.     */
  1204.  
  1205.     if (token == NULL) {
  1206.         /* Missing command parameters */
  1207.         pager(0);
  1208.         printf(cli$_insfprm);
  1209.     }
  1210.  
  1211.     return token;
  1212. }
  1213.  
  1214. /***********************************************************************
  1215.     get_rest_of_line_opt
  1216. ***********************************************************************/
  1217.  
  1218. static char *get_rest_of_line_opt(void)
  1219. {
  1220.     static char sep[] = "";
  1221.     char *token;
  1222.  
  1223.     /*
  1224.     // Get the rest of the line (optional).
  1225.     */
  1226.  
  1227.     token = strtok(NULL, sep);
  1228.     return token;
  1229. }
  1230.  
  1231. /***********************************************************************
  1232.     check_maxparm
  1233. ***********************************************************************/
  1234.  
  1235. static int check_maxparm(void)
  1236. {
  1237.     static char sep[] = " \t";
  1238.     char *token;
  1239.  
  1240.     /*
  1241.     // Get the next token (there shouldn't be one).
  1242.     */
  1243.  
  1244.     token = strtok(NULL, sep);
  1245.     strupr(token);
  1246.  
  1247.     /*
  1248.     // Well?
  1249.     */
  1250.  
  1251.     if (token == NULL) {
  1252.         /* No more parameters - OK */
  1253.         return 1;
  1254.     } else {
  1255.         /* Too many parameters */
  1256.         pager(0);
  1257.         printf(cli$_maxparm);
  1258.         pager(0);
  1259.         printf(cli$_cmdseg,token);
  1260.         return 0;
  1261.     }
  1262. }
  1263.  
  1264. /***********************************************************************
  1265.     get_address
  1266. ***********************************************************************/
  1267.  
  1268. static int get_address(bin5_t *adr)
  1269. {
  1270.     char *token;
  1271.     int status;
  1272.  
  1273.     if (token = get_next_token("_Address: ")) {
  1274.         status = convert_address(token,adr);
  1275.     } else {
  1276.         status = 0;
  1277.     }
  1278.  
  1279.     if (status) last_address = *adr;
  1280.  
  1281.     return status;
  1282. }
  1283.  
  1284. /***********************************************************************
  1285.     get_address_opt
  1286. ***********************************************************************/
  1287.  
  1288. static int get_address_opt(bin5_t *adr)
  1289. {
  1290.     char *token;
  1291.     int status;
  1292.  
  1293.     if (token = get_next_token_opt()) {
  1294.         status = convert_address(token,adr);
  1295.     } else {
  1296.         status = 1;
  1297.         *adr = WorkPtr;
  1298.     }
  1299.  
  1300.     if (status) last_address = *adr;
  1301.  
  1302.     return status;
  1303. }
  1304.  
  1305. /***********************************************************************
  1306.     get_address_range
  1307. ***********************************************************************/
  1308.  
  1309. static int get_address_range(bin5_t *start, bin5_t *end)
  1310. {
  1311.     char *token;
  1312.     char *p;
  1313.     int status = 1;
  1314.  
  1315.     if (token = get_next_token("_Address range: ")) {
  1316.         if (p = strchr(token,':')) {
  1317.             *p++ = '\0';
  1318.  
  1319.             if (*token) status = convert_address(token,start);
  1320.             else *start = 0x00000;
  1321.             
  1322.             if (*p) status = convert_address(p,end);
  1323.             else *end = 0xFFFFF;
  1324.  
  1325.         } else {
  1326.             status = convert_address(token,start);
  1327.             *end = *start;
  1328.         }
  1329.     } else {
  1330.         status = 0;
  1331.     }
  1332.  
  1333.     if (status) last_address = *start;
  1334.  
  1335.     return status;
  1336. }
  1337.  
  1338. /***********************************************************************
  1339.     get_dec_number
  1340. ***********************************************************************/
  1341.  
  1342. static int get_dec_number(char *prompt, bin5_t *number)
  1343.  
  1344. {
  1345.     char *token;
  1346.     char *p;
  1347.  
  1348.     if (token = get_next_token(prompt)) {
  1349.         /*
  1350.         // Convert text to integer and check validity.
  1351.         */
  1352.  
  1353.         *number = strtol(token, &p, 10);
  1354.  
  1355.         switch (*p) {
  1356.             case '\0':
  1357.             case ' ':
  1358.             case '\t':
  1359.             break;
  1360.  
  1361.             default:
  1362.             /* Invalid numeric value */
  1363.             pager(0);
  1364.             printf(cli$_ivchar);
  1365.             pager(0);
  1366.             printf(cli$_cmdseg,token);
  1367.             return 0;
  1368.         }
  1369.     } else {
  1370.         return 0;
  1371.     }
  1372.  
  1373.     return 1;
  1374. }
  1375.  
  1376. /***********************************************************************
  1377.     get_hex_number
  1378. ***********************************************************************/
  1379.  
  1380. static int get_hex_number(char *prompt, bin5_t *number)
  1381. {
  1382.     char *token;
  1383.     char *p;
  1384.  
  1385.     if (token = get_next_token(prompt)) {
  1386.         /*
  1387.         // Convert text to integer and check validity.
  1388.         */
  1389.  
  1390.         *number = str2adr(token, &p);
  1391.  
  1392.         switch (*p) {
  1393.             case '\0':
  1394.             case ' ':
  1395.             case '\t':
  1396.             break;
  1397.  
  1398.             default:
  1399.             /* Invalid numeric value */
  1400.             pager(0);
  1401.             printf(cli$_ivchar);
  1402.             pager(0);
  1403.             printf(cli$_cmdseg,token);
  1404.             return 0;
  1405.         }
  1406.     } else {
  1407.         return 0;
  1408.     }
  1409.  
  1410.     return 1;
  1411. }
  1412.  
  1413. /***********************************************************************
  1414.     convert_address
  1415. ***********************************************************************/
  1416.  
  1417. static int convert_address(char *token, bin5_t *adr)
  1418. {
  1419.     char *p;
  1420.     int status = 1;
  1421.  
  1422.     if (!strcmp(token,".")) {
  1423.         /*
  1424.         // Current address.
  1425.         */
  1426.  
  1427.         *adr = WorkPtr;
  1428.  
  1429.     } else if (!strcmp(token,"$")) {
  1430.         /*
  1431.         // Last address.
  1432.         */
  1433.  
  1434.         *adr = last_address;
  1435.  
  1436.     } else {
  1437.         /*
  1438.         // Get specified address.
  1439.         */
  1440.  
  1441.         *adr = str2adr(token, &p);
  1442.  
  1443.         switch (*p) {
  1444.             case '\0':
  1445.             case ' ':
  1446.             case '\t':
  1447.             break;
  1448.  
  1449.             default:
  1450.             /* Invalid numeric value */
  1451.             pager(0);
  1452.             printf(cli$_ivchar);
  1453.             pager(0);
  1454.             printf(cli$_cmdseg,token);
  1455.             status = 0;
  1456.         }
  1457.     }
  1458.  
  1459.     return status;
  1460. }
  1461.